using System.Collections.Generic;
using ZFramework;
using ZFramework.Voxel;

namespace PaintAWorld
{
    public class LocalWorld : IWorld, IMessenger
    {
        private readonly WorldLogic _logic;
        private readonly Queue<IGameEvent> _eventQueue = new();

        public LocalWorld()
        {
            _logic = new(this);
        }

        public LocalWorld(VoxelModel model)
        {
            _logic = new(this, model);
        }

        public void Broadcast(IGameEvent gameEvent)
        {
            _eventQueue.Enqueue(gameEvent);
        }

        public bool PollEvent(out IGameEvent gameEvent)
        {
            gameEvent = null;
            if (_eventQueue.Count > 0)
            {
                gameEvent = _eventQueue.Dequeue();
                return true;
            }
            return false;
        }

        public void DispatchInput(PlayerInput input) => _logic.DispatchInput(input);

        public void RemoveVoxel(Vec3I voxelPos)
        {
            _logic.RemoveVoxel(voxelPos);
        }

        public void RemoveVoxelBatched(IEnumerable<Vec3I> voxelPositions)
        {
            _logic.RemoveVoxelBatched(voxelPositions);
        }

        public void RunCommand(string command)
        {
            if (ParseCommand(command) is ICommand cmd)
                ExecuteCommand(cmd);
        }

        private ICommand ParseCommand(string cmd)
        {
            var args = cmd.Split(' ');
            return args[0] switch
            {
                "set" => SetVoxelCommand.Parse(args[1..]),
                "rm" => RmVoxelCommand.Parse(args[1..]),
                _ => null,
            };
        }

        private void ExecuteCommand(ICommand command)
        {
            command.Execute(_logic);
        }

        public void SetVoxel(Vec3I voxelPos, Rgba32 color)
        {
            _logic.SetVoxel(voxelPos, color);
        }

        public void SetVoxelBatched(IEnumerable<Vec3I> voxelPositions, Rgba32 color)
        {
            _logic.SetVoxelBatched(voxelPositions, color);
        }

        public IVoxelMap<Rgba32> GetMap() => _logic;

    }
}